<template>
  <div class="be-table" :class="[$attrs.class, { 'be-resize-table': canResize }, clearPadding ? 'clearPadding' : '']" ref="tableWrapper">
    <!-- 搜索区域，默认显示，通过 showSearch 控制 -->
    <div class="be-table__search" v-if="showSearch">
      <slot name="search" :onSearch="handleSearch" :formSetting="getBindFormSetting">
        <BeForm v-if="formSetting" v-bind="getBindFormSetting" @search="handleSearch" ref="formRefs" />
      </slot>
    </div>

    <!-- 工具栏区域，默认显示，通过 showToolbar 控制 -->
    <div class="be-table__toolbar" v-if="showToolbar && $slots.toolbar">
      <slot name="toolbar"></slot>
    </div>

    <!-- 表格主体 -->
    <a-table
      v-bind="getBindValue"
      :columns="visibleColumns"
      :pagination="paginationConfig"
      :data-source="tableData"
      :loading="showLoading ? innerLoading : false"
      :scroll="computedScroll"
      @change="onTableChange"
      class="be-table__wrapper"
    >
      <!-- 透传所有插槽，实现 a-table 的插槽功能完全支持 -->
      <template v-for="(_, slotName) in $slots" #[slotName]="slotScope">
        <slot :name="slotName" v-bind="slotScope"></slot>
      </template>
      <template #emptyText>
        <div v-if="!innerLoading" class="empty-wrap">
          <BeIcon icon="local:empty" class="empty-icon" />
          <p class="empty-text">暂无数据</p>
        </div>
      </template>
    </a-table>
  </div>
</template>

<script setup lang="ts">
import type { TablePaginationConfig } from 'ant-design-vue'
import { ref, computed, onMounted, watch } from 'vue'
import { Props as FormSetting } from '@/components/basics/BeForm'

interface FetchSetting {
  pageField: string
  sizeField: string
  listField: string
  totalField: string
}

// 组件传入的 props 类型定义
interface Props {
  columns: any[] // 表格列配置
  dataSource?: any[] // 本地数据源，和 api 二选一
  pagination?: false | TablePaginationConfig // 分页配置，false 关闭分页
  scroll?: { x?: number | string; y?: number } // 滚动配置
  api?: (_params: any) => Promise<any> // 数据接口请求函数
  beforeFetch?: (_params: any) => any // 请求前参数处理函数
  afterFetch?: (_result: any) => any // 请求后数据处理函数
  canResize?: boolean // 自适应高度
  showLoading?: boolean // 是否显示加载状态
  loading?: boolean // 外部控制加载状态
  showSearch?: boolean // 是否显示搜索区域
  showToolbar?: boolean // 是否显示工具栏区域
  fetchSetting?: Partial<FetchSetting> // 数据请求配置，包含分页字段等
  formSetting?: FormSetting // 表单配置，包含搜索表单字段等
  immediate?: boolean // 是否在组件挂载时立即加载数据
  clearPadding?: boolean //是否清空padding
}

defineOptions({ name: 'BeTable', inheritAttrs: false })

// 定义 props，设置默认值
const props = withDefaults(defineProps<Props>(), {
  rowKey: 'id',
  pagination: () => false,
  scroll: () => ({}),
  canResize: true,
  showLoading: true,
  showSearch: true,
  showToolbar: true,
  immediate: true,
  fetchSetting: () => ({
    pageField: 'page',
    sizeField: 'size',
    listField: 'data',
    totalField: 'total'
  }),
  clearPadding: false
})

// emit
const emit = defineEmits(['search', 'change', 'update:pagination'])
const formRefs = ref()
// state
const attrs = useAttrs() // 获取组件的所有属性
const tableWrapper = ref<HTMLElement | null>(null) // DOM 容器引用，用于计算高度
const innerScroll = ref({ x: '100%', y: 500 }) // 内部维护的滚动配置，初始值设定
const innerLoading = ref(false) // 是否显示加载状态
const tableData = ref<any[]>([]) // 当前表格展示的数据列表
const searchParams = ref({}) // 搜索条件参数，动态维护
const visibleColumns = computed(() => props.columns.filter((col: any) => col.visible !== false)) // 过滤出显示的列，用于传给 a-table
const isLocalMode = computed(() => !props.api && Array.isArray(props.dataSource)) // 判断是本地数据模式（无 api 且传入了 dataSource）
const paginationData = ref<TablePaginationConfig>({
  ...{ current: 1, pageSize: 15, showQuickJumper: true, showSizeChanger: true, pageSizeOptions: ['10', '15', '20', '30', '50', '100', '150', '200'] }, //showTotal: (total: number) => `共 ${total} 条`
  ...(props.pagination ?? {})
})
const paginationConfig = computed(() => (props.pagination === false ? false : paginationData.value)) // 分页配置
const getBindValue = computed(() => {
  const { class: _class, ...rest } = attrs
  return rest
})
const getBindFormSetting = computed<FormSetting>(() => {
  const fields = (props.formSetting?.fields || []).map((field) => {
    const colProps = field.colProps || {}
    return { ...field, colProps: { xs: 24, sm: 12, md: 8, lg: 6, xl: 6, xxl: 6, ...props.formSetting?.colProps, ...colProps } }
  })
  return { maxShowFields: 4, showAction: true, showSearchButton: true, showResetButton: true, showExpandButton: true, ...props.formSetting, fields }
})

// 计算最终传给 a-table 的 scroll 配置（x 和 y）
const computedScroll = computed(() => ({
  x: props.scroll?.x ?? innerScroll.value.x,
  // y: props.canResize ? innerScroll.value.y : props.scroll?.y
  y: props.scroll?.y || '100%'
}))

// 计算横向滚动宽度（列宽总和）  如果 props.scroll.x 已经定义，则不重新计算
const computeScrollX = () => {
  if (props.scroll?.x !== undefined) return
  // 计算所有可见列宽度总和，默认宽度120
  const totalWidth = visibleColumns.value.reduce((sum: number, col: any) => sum + (parseInt(col.width) || 120), 0)
  innerScroll.value.x = totalWidth as unknown as string
}

// 改成样式实现了，不使用js计算 计算纵向滚动高度（容器高度减去底部间隙） 仅在 canResize=true 且容器存在时计算
// const computeScrollY = () => {
//   requestAnimationFrame(() => {
//     if (!props.canResize || !tableWrapper.value) return
//     const tableHeight = tableWrapper.value.querySelector('.ant-table-wrapper')?.clientHeight || 0
//     console.log(tableHeight)
//     const headHeight = tableWrapper.value.querySelector('.ant-table-thead')?.clientHeight || 0
//     const paginationHeight = tableWrapper.value.querySelector('.ant-pagination')?.clientHeight || 0
//     innerScroll.value.y = tableHeight - headHeight - paginationHeight
//   })
// }

// 处理尺寸改变事件，重新计算纵向滚动高度
// let resizeObserver: any = null
// const handleResizeObserver = () => {
//   if (props.canResize) {
//     const searchEl = tableWrapper.value?.querySelector('.be-table__search')
//     const toolbarEl = tableWrapper.value?.querySelector('.be-table__toolbar')
//     resizeObserver = new ResizeObserver((entries) => {
//       entries.forEach(() => {
//         computeScrollY()
//       })
//     })
//     // 遍历绑定每个元素
//     const boxes = [searchEl, toolbarEl]
//     boxes.forEach((box: any) => resizeObserver.observe(box))
//   }
// }

// 加载数据函数，支持本地数据和接口请求两种模式
const loadData = async () => {
  try {
    if (isLocalMode.value) {
      tableData.value = props.dataSource ?? [] // 本地数据直接赋值
    } else if (props.api) {
      innerLoading.value = true
      const { pageField, sizeField, listField, totalField } = props.fetchSetting
      const current = (paginationData.value as TablePaginationConfig).current
      const pageSize = (paginationData.value as TablePaginationConfig).pageSize
      // 远程请求参数，包含分页和搜索条件
      let params: any = {
        [pageField!]: current! - 1, // 这里为-1是因为后台分页从0开始，坑
        [sizeField!]: pageSize,
        ...searchParams.value
      }
      // 请求前处理
      if (props.beforeFetch) {
        params = props.beforeFetch(params)
      }
      const response: any = await props.api(params)
      // 处理后端数据
      let list: any[] = []
      let total = 0
      if (props.afterFetch) {
        const result = props.afterFetch(response)
        list = result.data
        total = result.total
      } else {
        list = response[listField!] || []
        total = response[totalField!] || 0
      }
      tableData.value = Array.isArray(list) ? list : []
      paginationData.value.total = total || 0
    }
  } catch (err) {
    console.error('loadData error:', err)
    tableData.value = []
    paginationData.value.total = 0
  } finally {
    innerLoading.value = false
  }
}

// 搜索触发事件，重置分页并加载数据
const handleSearch = async (params: Record<string, any>) => {
  params = JSON.parse(JSON.stringify(params))
  searchParams.value = { ...params } // 深拷贝，避免引用问题
  paginationData.value.current = 1
  emit('search', searchParams.value)
  await loadData()
}

// 表格分页、排序、筛选等变化事件
const onTableChange = async (pag: any) => {
  paginationData.value.current = pag.current
  paginationData.value.pageSize = pag.pageSize
  emit('change', pag)
  emit('update:pagination', paginationData.value)
  loadData()
}

// 监听外部 pagination 变化，同步更新内部分页状态
watch(
  () => props.pagination,
  (val: any) => {
    if (val !== false) {
      paginationData.value = { ...paginationData.value, ...val }
    }
  },
  { immediate: true, deep: true }
)

// 监听外部的加载状态，可由外部控制
watch(
  () => props.loading,
  () => {
    innerLoading.value = props.loading
  }
)

// 监听 visibleColumns 变化，重新计算横向滚动宽度
watch(visibleColumns, computeScrollX, { deep: true })

// 组件挂载后，计算滚动区域大小并加载数据
onMounted(() => {
  computeScrollX()
  if (props.immediate) {
    loadData()
  }
  // if (props.canResize) {
  //   computeScrollY()
  //   handleResizeObserver()
  //   window.addEventListener('resize', computeScrollY)
  // }
})

// 在组件卸载时清除监听
onUnmounted(() => {
  // if (props.canResize) {
  //   window.removeEventListener('resize', computeScrollY)
  //   resizeObserver.disconnect()
  // }
})
const setDataSource = (data: any) => {
  tableData.value = data
}
// 暴露方法
defineExpose({
  reload: loadData,
  getDataSource: () => tableData.value,
  setPagination: (pagination: TablePaginationConfig) => {
    paginationData.value = { ...paginationData.value, ...pagination }
    emit('update:pagination', paginationData.value)
  },
  setDataSource,
  formRefs: formRefs
})
</script>

<style lang="scss">
.be-table {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: auto;
  padding: 12px;
  background-color: var(--color-white);

  &__search {
    position: relative;
    overflow: hidden;
    margin-bottom: 5px;
    padding-bottom: 5px;
    .be-form {
      padding: 0 !important;
      .ant-form-item {
        padding-bottom: 5px !important;
        margin-bottom: 0px !important;
      }
    }
  }
  &__toolbar {
    position: relative;
    display: flex;
    gap: 8px;
    padding: 0px 0 12px 0px;
    overflow: hidden;
    background-color: var(--color-white);
  }
  &.be-resize-table {
    .ant-table-wrapper {
      flex: 1;
      overflow: hidden;
    }
    .ant-spin-nested-loading,
    .ant-spin-container,
    .ant-table {
      display: flex;
      flex: 1;
      flex-direction: column;
      height: 100%;
      overflow: hidden;
    }
    .ant-table-container {
      display: flex;
      flex-direction: column;
      height: 100%;
      .ant-table-body {
        flex: 1;
        max-height: initial !important;
        overflow: auto;
      }
    }
  }
  .ant-table-wrapper {
    .ant-table-pagination.ant-pagination {
      padding: 16px;
      margin: 0;
      background-color: var(--color-white);
      .ant-pagination-item {
        &.ant-pagination-item-active {
          color: var(--color-white);
          background-color: var(--primary);
          a {
            font-weight: normal;
            color: inherit;
          }
        }
      }
    }
    .ant-table-cell::before {
      display: none;
    }
    .ant-table-thead {
      .ant-table-cell {
        padding: 8px;
        font-size: 13px;
      }
    }
    .ant-table-body {
      .ant-table-cell {
        padding: 6px;
        font-size: 13px;
      }
    }
    .ant-table-container {
      .ant-table-body tr.ant-table-placeholder {
        .ant-table-cell {
          border-bottom: none;
        }
      }
    }
    .empty-wrap {
      display: flex;
      flex-direction: column;
      align-items: center;
      .empty-icon {
        font-size: 60px;
      }
    }
  }
}
.clearPadding {
  padding: 0 !important;
}
td {
  white-space: nowrap; /* 1. 强制文本在一行内显示 */
  overflow: hidden; /* 2. 隐藏超出单元格的内容 */
  text-overflow: ellipsis; /* 3. 用省略号 "..." 表示被截断的文本 */
}
// .ant-select-single .ant-select-selector {
//   border-radius: 0;
// }
// .ant-pagination .ant-pagination-disabled,
// .ant-pagination .ant-pagination-next,
// .ant-pagination .ant-pagination-prev {
//   min-width: 24px;
//   height: 24px;
//   margin: 0;
//   line-height: 24px;
// }
// .ant-pagination .ant-pagination-item {
//   min-width: 24px;
//   height: 24px;
//   margin: 0;
//   line-height: 22px;
// }
// .be-table .ant-table-wrapper .ant-table-pagination.ant-pagination .ant-pagination-item.ant-pagination-item-active {
//   color: #1890ff;
//   background: none;
// }
// :where(.css-dev-only-do-not-override-10npqub).ant-select-single .ant-select-selector .ant-select-selection-item,
// :where(.css-dev-only-do-not-override-10npqub).ant-select-single .ant-select-selector .ant-select-selection-placeholder {
//   line-height: 22px;
// }
// :where(.css-dev-only-do-not-override-10npqub).ant-select-single:not(.ant-select-customize-input) .ant-select-selector {
//   height: 24px;
//   padding: 0 8px;
// }
// :where(.css-dev-only-do-not-override-10npqub).ant-pagination .ant-pagination-options-quick-jumper input {
//   height: 24px;
//   border-radius: 0;
//   width: 44px;
//   padding: 0 7px;
// }
// :where(.css-dev-only-do-not-override-10npqub).ant-pagination .ant-pagination-options-quick-jumper {
//   height: 24px;
//   line-height: 24px;
// }
// .be-table .ant-table-wrapper .ant-table-thead .ant-table-cell {
//   padding: 8px;
// }
// .ant-upload-wrapper .ant-upload-drag,
// .ant-input,
// .ant-btn.ant-btn-lg {
//   border-radius: 2px;
// }
// .ant-select-single.ant-select-lg .ant-select-selector {
//   border-radius: 2px;
// }
// :where(.css-10npqub).ant-tabs-card.ant-tabs-top > .ant-tabs-nav .ant-tabs-tab,
// :where(.css-10npqub).ant-tabs-card.ant-tabs-top > div > .ant-tabs-nav .ant-tabs-tab {
//   border-radius: 0;
// }
</style>
